package com.portal.encryption.utils;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import java.nio.charset.StandardCharsets;
import java.security.Security;

/**
 * AES加密工具类
 *
 * @author Amadeus
 * @date 2022/07/04
 */
@Slf4j
public class AesEncryptionUtils {
    private static final String AES = "AES";
    private static final String ALGORITHM = "AES/CBC/PKCS7Padding";

    static {
        try {
            Security.addProvider(new BouncyCastleProvider());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * @param data 明文
     * @return 密文
     * @author miracle.qu
     * @Description AES算法加密明文
     */
    public static String encryptAES(String data, String key, String iv) {
        try {

            Cipher cipher = Cipher.getInstance(ALGORITHM);

            SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), AES);
            // CBC模式，需要一个向量iv，可增加加密算法的强度
            IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8));

            cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
            byte[] encrypted = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
            // BASE64做转码。
            return AesEncryptionUtils.encode(encrypted).trim();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * @param data 密文
     * @return 明文
     * @author miracle.qu
     * @Description AES算法解密密文
     */
    public static String decryptAES(String data, String key, String iv) {
        try {
            //先用base64解密
            byte[] encrypted1 = AesEncryptionUtils.decode(data);

            Cipher cipher = Cipher.getInstance(ALGORITHM);
            SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), AES);
            IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8));

            cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);

            byte[] original = cipher.doFinal(encrypted1);
            String originalString = new String(original);
            return originalString.trim();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 编码
     *
     * @param byteArray 字节数组
     * @return {@link String}
     */
    public static String encode(byte[] byteArray) {
        return new String(new Base64().encode(byteArray));
    }

    /**
     * 解码
     *
     * @param base64EncodedString base64编码的字符串
     * @return {@link byte[]}
     */
    public static byte[] decode(String base64EncodedString) {
        return new Base64().decode(base64EncodedString);
    }

    public static void main(String[] args) {

        //body加密测试
        String str = "{\n" +
                "\"dealerCode\":\"SZ111\",\n" +
                "\"messageType\":10,\n" +
                "\"dealerName\":\"深圳门店\",\n" +
                "\"activityId\":\"1\",\n" +
                "\"reqFrom\":1,\n" +
                "\"sendTo\":\"1\",\n" +
                "\"province\":\"浙江\",\n" +
                "\"city\":\"杭州\",\n" +
                "\"sendToPhone\":\"13857739176\",\n" +
                "\"showTime\":1655187673898,\n" +
                "\"skipType\":2,\n" +
                "\"subType\":50,\n" +
                "\"type\":2\n" +
                "}";
        String encryptAES = encryptAES(str, "F27B210AB1F6477482459B214BB4924B", "05631CF6A3334D03");
        log.info(encryptAES);

        String decryptAES = decryptAES(encryptAES, "F27B210AB1F6477482459B214BB4924B", "05631CF6A3334D03");
        log.info(decryptAES);
    }
}
